﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Security.Permissions;
using System.Security.Principal;
using System.Windows.Forms;
using BGShell.Components;
using BGShell.Controls;
using WindowsFormsAero;

namespace BGShell.Forms
{
    public sealed partial class MainForm : Form
    {
        private readonly String _titleSuffix = "BGShell";

        private Type _firstTabType;

        internal MainForm()
        {
            InitializeComponent();

            if (IsAdmin)
            {
                _titleSuffix += Resources.AdministratorTitleSuffix;
            }

            MenuBarVisible = (Environment.OSVersion.Version.Major < 6);
            Icon = ResourcesNative.BGShellIcon;
            Text = _titleSuffix;
        }

        internal MainForm(bool isBackground)
            : this()
        {
            keyboardHook.Enabled = isBackground;

            if (isBackground)
            {
                tabs.CloseButton.Visibility = CloseButtonVisibility.ExceptSingleTab;
            }
        }

        public void Show(Type tabType)
        {
            if (tabType != null)
            {
                _firstTabType = tabType;
            }

            Show();
        }

        public void OpenTab(BGShellTabPage page)
        {
            if (page == null)
            {
                throw new ArgumentNullException("page");
            }

            if (page.TabControl == null)
            {
                tabs.TabPages.Add(page);
            }
            
            if (page.TabControl == tabs)
            {
                tabs.SelectedTab = page;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }

            base.Dispose(disposing);
        }

        [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogKey(Keys keyData)
        {
            const Keys AltShiftEnter = Keys.Alt | Keys.Shift | Keys.Enter;

            if ((keyData == AltShiftEnter) || (keyData == Keys.F11))
            {
                IsFullScreen = !IsFullScreen;
                return true;
            }

            return base.ProcessDialogKey(keyData);
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();

            if (!DesignMode && !IsBackgroundWindow)
            {
                OpenFirstTab();
            }
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (IsBackgroundWindow && (e.CloseReason == CloseReason.UserClosing))
            {
                e.Cancel = true;
                Hide();
            }
            else
            {
                base.OnFormClosing(e);

                if (!e.Cancel)
                {
                    menuStripHider.KeepHiddenAfterDispose = true;

                    if (DesktopComposition.IsEnabled)
                    {
                        RedrawHelper.SetRedrawRecursively(this, false);
                    }
                }
            }
        }

        internal void OpenFirstTab()
        {
            tabs.OpenTab(_firstTabType);
        }

        internal KeyboardHook KeyboardHook
        {
            get { return keyboardHook; }
        }

        private void OnLastTabClosed(object sender, EventArgs e)
        {
            BGShellApplication.Current.ExitCode = tabs.LastExitCode;
            Close();
        }

        private void OnSelectedTabTextChanged(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(tabs.Text))
            {
                Text = tabs.Text + " - " + _titleSuffix;
            }
            else
            {
                Text = _titleSuffix;
            }
        }

        private void OnSelectedTabChanged(object sender, EventArgs e)
        {
            var zoomableTab = tabs.SelectedTab as IZoomableTabPage;

            if (zoomableTab != null)
            {
                zoomableTab.ZoomFactorChanged += OnZoomFactorChanged;
            }

            OnZoomFactorChanged(this, EventArgs.Empty);
        }

        private void OnSelectedTabChanging(object sender, CancelEventArgs e)
        {
            var zoomableTab = tabs.SelectedTab as IZoomableTabPage;

            if (zoomableTab != null)
            {
                zoomableTab.ZoomFactorChanged -= OnZoomFactorChanged;
            }
        }

        private void OnZoomFactorChanged(object sender, EventArgs e)
        {
            var tab = tabs.SelectedTab as IZoomableTabPage;
            var zf = 1.0f;

            if (tab != null)
            {
                zf = tab.ZoomFactor;
            }

            zoomContextMenu.ZoomFactor = zf;
            mnuStatusZoom.Text = zf.ToString("P0", CultureInfo.CurrentCulture);
        }

        private void mnuStatusZoom_ButtonClick(object sender, EventArgs e)
        {
            if (zoomContextMenu.ZoomFactor == 1.0f)
            {
                zoomContextMenu.ZoomFactor = 1.25f;
            }
            else if (zoomContextMenu.ZoomFactor == 1.25f)
            {
                zoomContextMenu.ZoomFactor = 1.5f;
            }
            else
            {
                zoomContextMenu.ZoomFactor = 1.0f;
            }
        }

        private void mnuFile_DropDownOpening(object sender, EventArgs e)
        {
            var type = BGShellApplication.Current.AddInManager.DefaultTabType;

            mnuFileNewWindow.Enabled = (type != null);
            mnuFileNewTab.Enabled = (type != null);

            mnuFileCloseTab.Enabled = CanCloseTab;
            mnuFileExit.Text = IsLastForm ? Resources.Exit : Resources.Close;
        }

        private void mnuFileNewWindow_Click(object sender, EventArgs e)
        {
            BGShellApplication.Current.Windows.Open();
        }

        private void mnuFileNewTab_Click(object sender, EventArgs e)
        {
            tabs.OpenTab();
        }

        private void mnuFileCloseTab_Click(object sender, EventArgs e)
        {
            tabs.CloseSelectedTab();
        }

        private void mnuFileExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void mnuEdit_DropDownOpening(object sender, EventArgs e)
        {
            var tab = tabs.SelectedTab as IEditableTabPage;

            mnuEditCut.Enabled = (tab != null) && tab.CanCut;
            mnuEditCopy.Enabled = (tab != null) && tab.CanCopy;
            mnuEditPaste.Enabled = (tab != null) && tab.CanPaste;
            mnuEditSelectAll.Enabled = (tab != null) && tab.CanSelectAll;
        }

        private void mnuEditItems_Click(object sender, EventArgs e)
        {
            var tab = tabs.SelectedTab as IEditableTabPage;

            if (tab != null)
            {
                if (sender == mnuEditCut)
                {
                    tab.Cut();
                }
                else if (sender == mnuEditCopy)
                {
                    tab.Copy();
                }
                else if (sender == mnuEditPaste)
                {
                    tab.Paste();
                }
                else if (sender == mnuEditSelectAll)
                {
                    tab.SelectAll();
                }
            }
        }

        private void mnuView_DropDownOpening(object sender, EventArgs e)
        {
            mnuViewMenuBar.Checked = MenuBarVisible;
            mnuViewStatusBar.Checked = statusStrip.Visible;
            mnuViewFullScreen.Checked = IsFullScreen;
        }

        private void mnuViewMenuBar_Click(object sender, EventArgs e)
        {
            MenuBarVisible = !MenuBarVisible;
        }

        private void mnuViewStatusBar_Click(object sender, EventArgs e)
        {
            StatusBarVisible = !StatusBarVisible;
        }
        
        private void mnuViewTextSize_DropDownOpening(object sender, EventArgs e)
        {
            foreach (ToolStripMenuItem item in mnuViewTextSize.DropDownItems)
            {
                item.Checked = false;
            }

            var zf = ZoomFactor;

            if (zf >= 1.5f)
            {
                mnuViewTextLargest.Checked = true;
            }
            else if (zf > 1.0f)
            {
                mnuViewTextLarge.Checked = true;
            }
            else if (zf < 0.85f)
            {
                mnuViewTextSmallest.Checked = true;
            }
            else if (zf < 1.0f)
            {
                mnuViewTextSmall.Checked = true;
            }
            else
            {
                mnuViewTextMedium.Checked = true;
            }
        }

        private void mnuViewTextSize_Click(object sender, EventArgs e)
        {
            if (sender == mnuViewTextLargest)
            {
                ZoomFactor = 1.5f;
            }
            else if (sender == mnuViewTextLarge)
            {
                ZoomFactor = 1.25f;
            }
            else if (sender == mnuViewTextSmall)
            {
                ZoomFactor = 0.85f;
            }
            else if (sender == mnuViewTextSmallest)
            {
                ZoomFactor = 0.75f;
            }
            else
            {
                ZoomFactor = 1.0f;
            }
        }

        private void mnuToolsOptions_Click(object sender, EventArgs e)
        {
            MessageBox.Show(this, "Sorry, no options yet.", ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);

            //using (var optionsForm = new OptionsForm())
            //{
            //    if (optionsForm.ShowDialog(this) == DialogResult.OK)
            //    {
            //    }
            //}
        }

        private void mnuHelpViewHelp_Click(object sender, EventArgs e)
        {
#if HELP
            BGShellApplication.Current.OpenHelpWindow(CurrentHelpTopic);
#else
            MessageBox.Show(this, "Sorry, no help yet.", ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
#endif
        }

        private void mnuHelpAbout_Click(object sender, EventArgs e)
        {
            using (var form = new AboutForm())
            {
                form.ShowDialog(this);
            }
        }

        private void mnuFullScreen_CheckedChanged(object sender, EventArgs e)
        {
            var button = sender as ToolStripButton;
            var menuItem = sender as ToolStripMenuItem;

            if (button != null)
            {
                IsFullScreen = button.Checked;
            }
            else if (menuItem != null)
            {
                IsFullScreen = menuItem.Checked;
            }
        }

        private void zoomContextMenu_ZoomFactorChanged(object sender, EventArgs e)
        {
            ZoomFactor = zoomContextMenu.ZoomFactor;
        }

        private bool CanCloseTab
        {
            get 
            {
                if (IsBackgroundWindow)
                {
                    return tabs.TabPages.Count > 1;
                }

                return (tabs.SelectedTab != null);
            }
        }

        private bool IsBackgroundWindow
        {
            get { return this == BGShellApplication.Current.Windows.BackgroundWindow; }
        }

        private bool IsFullScreen
        {
            get { return fullScreen.GetFullScreen(this); }
            set
            {
                fullScreen.SetFullScreen(this, value);

                mnuFullScreen.Visible = value;
                mnuFullScreen.Checked = value;
                mnuViewFullScreen.Checked = value;
            }
        }

        private bool MenuBarVisible
        {
            get { return !menuStripHider.GetHideWhenInactive(MainMenuStrip); }
            set
            {
                menuStripHider.SetHideWhenInactive(MainMenuStrip, !value);
                mnuViewMenuBar.Checked = value;

                if (value)
                {
                    menuStrip.SendToBack();
                }
                else
                {
                    menuStrip.BringToFront();
                }
            }
        }

        private bool StatusBarVisible
        {
            get { return statusStrip.Visible; }
            set
            {
                if (value)
                {
                    statusStrip.SendToBack();
                }

                mnuViewStatusBar.Checked = value;
                statusStrip.Visible = value;
            }
        }

        private float ZoomFactor
        {
            get
            {
                var tab = tabs.SelectedTab as IZoomableTabPage;

                if (tab != null)
                {
                    return tab.ZoomFactor;
                }

                return 1.0f;
            }
            set
            {
                var tab = tabs.SelectedTab as IZoomableTabPage;

                if (tab != null)
                {
                    if (Math.Abs(tab.ZoomFactor - value) > 0.01f)
                    {
                        tab.ZoomFactor = value;
                    }
                }
            }
        }

        private static bool IsAdmin
        {
            get
            {
                using (var identity = WindowsIdentity.GetCurrent())
                {
                    return new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator);
                }
            }
        }

        private static bool IsLastForm
        {
            get { return BGShellApplication.Current.Windows.NextCloseWillExit; }
        }
    }
}